/*
 * Copyright 2007-2008 Andrew O'Malley
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


package ws.quokka.plugin.maven;

import ws.quokka.core.repo_spi.Repository;
import ws.quokka.core.repo_spi.UnresolvedArtifactException;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;


/**
 *
 */
public class ResolvedMavenArtifact {
    //~ Instance fields ------------------------------------------------------------------------------------------------

    private String description;
    private Set licenses = new HashSet();
    private List dependencies = new ArrayList();
    private MavenDependency path;

    //~ Methods --------------------------------------------------------------------------------------------------------

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    public Set getLicenses() {
        return licenses;
    }

    public List getDependencies() {
        return dependencies;
    }

    public MavenDependency getPath() {
        return path;
    }

    public void setPath(MavenDependency path) {
        this.path = path;
    }

    public String toString() {
        StringBuffer sb = new StringBuffer();
        sb.append("Description: ").append((description == null) ? "" : description).append("\n");
        sb.append("Direct runtime dependencies:\n");

        for (Iterator i = dependencies.iterator(); i.hasNext();) {
            MavenDependency dependency = (MavenDependency)i.next();
            formatTree(sb, dependency, "    ");
        }

        sb.append("Transitive runtime path:\n");
        formatTree(sb, path, "    ");

        sb.append("Licenses:\n");

        for (Iterator i = licenses.iterator(); i.hasNext();) {
            LicenseMapping mapping = (LicenseMapping)i.next();
            sb.append("    ").append(mapping.getName()).append(" -> ");
            sb.append((mapping.getId() == null) ? "No mapping" : mapping.getId().toShortString());
        }

        return sb.toString();
    }

    public void formatTree(StringBuffer sb, MavenDependency dependency, String padding) {
        sb.append(padding).append(dependency.getMavenId().toString()).append(" -> ");
        sb.append((dependency.getId() == null) ? "No mapping" : dependency.getId().toShortString());
        sb.append(Boolean.TRUE.equals(dependency.getOptional()) ? ", optional" : "");
        sb.append(((dependency.getState() == null) || dependency.getState().equals("included")) ? ""
                                                                                                : (
                ", " + dependency.getState()
            ));

//        sb.append(dependency.isRequiresImport() ? "" : ", import needed");
        sb.append("\n");

        for (Iterator i = dependency.getDependencies().iterator(); i.hasNext();) {
            MavenDependency child = (MavenDependency)i.next();
            formatTree(sb, child, padding + "    ");
        }
    }

    public boolean containsUnmappedIds() {
        for (Iterator i = getAllDependencies().iterator(); i.hasNext();) {
            MavenDependency dependency = (MavenDependency)i.next();

            if (dependency.getId() == null) {
                return true;
            }
        }

        for (Iterator i = licenses.iterator(); i.hasNext();) {
            LicenseMapping mapping = (LicenseMapping)i.next();

            if ((mapping.getId() == null) && !mapping.isManual()) {
                return true;
            }
        }

        return false;
    }

    public List getPrerequisites(Repository repository) {
        List imports = new ArrayList();

        for (Iterator i = getAllDependencies().iterator(); i.hasNext();) {
            MavenDependency dependency = (MavenDependency)i.next();

            try {
                repository.resolve(dependency.getId(), false);
                dependency.setRequiresImport(false);
            } catch (UnresolvedArtifactException e) {
                dependency.setRequiresImport(true);
                imports.add(dependency.getMavenId());
            }
        }

        Collections.reverse(imports); // Do children before parents

        return imports;
    }

    public Collection getAllDependencies() {
        List deps = new ArrayList();

        for (Iterator i = dependencies.iterator(); i.hasNext();) {
            MavenDependency dependency = (MavenDependency)i.next();
            getAllDependencies(deps, dependency);
        }

        getAllDependencies(deps, path);

        return deps;
    }

    public void getAllDependencies(Collection dependencies, MavenDependency dependency) {
        dependencies.add(dependency);

        for (Iterator i = dependency.getDependencies().iterator(); i.hasNext();) {
            MavenDependency dep = (MavenDependency)i.next();
            getAllDependencies(dependencies, dep);
        }
    }
}
